/*************************************************************
 * Title: PrivilegeServiceImpl.java
 * Description: 
 * Author: Huang Shaobin
 * Email: shaobin.software@gmail.com
 * CreateTime: Feb 21, 2013 4:06:05 PM
 * Copyright © 落羽社区 All right reserved
 ************************************************************/
package snow.biz.security.service.impl;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import snow.biz.basic.service.impl.HibernateBaseServiceImpl;
import snow.biz.security.model.Privilege;
import snow.biz.security.service.IPrivilegeService;
import snow.biz.system.model.User;
import snow.core.domain.Pagination;
import snow.core.enums.Status;
import snow.core.exceptions.BusinessException;
import snow.core.persistence.AndedConditions;
import snow.core.persistence.BinaryOperator;
import snow.core.persistence.Condition;
import snow.core.persistence.Conditions;
import snow.core.persistence.Order;
import snow.core.security.Operator;
import snow.core.security.Permission;
import snow.core.security.SecurityHelper;
import snow.core.security.SecurityService;
import snow.core.security.annotations.Operation;
import snow.core.toolkit.ClassHelper;

/**
 * 权限操作的相关服务实现类
 */
public class PrivilegeServiceImpl extends HibernateBaseServiceImpl implements IPrivilegeService, SecurityService {

	private Integer superAdminUserId = Integer.valueOf(1);

	public Integer getSuperAdminUserId() {
		return this.superAdminUserId;
	}

	public Privilege searchPrivilegeFrom(Integer id) throws BusinessException {
		return super.get(Privilege.class, id);
	}

	public Pagination searchPrivilegesForPagingFrom(Conditions conditions, List<Order> orders, int start, int limit) throws BusinessException {
		return super.findForPaging(Privilege.class, conditions, orders, start, limit);
	}

	public List<Privilege> searchPrivilegesFrom(Conditions conditions, List<Order> orders, int start, int limit) throws BusinessException {
		return super.find(Privilege.class, conditions, orders, start, limit);
	}

	/**
	 * 初始化权限信息
	 * 
	 * @throws BusinessException
	 * @see snow.core.security.SecurityService#initializePermission()
	 */
	public void initializePermission() throws BusinessException {
		final SessionFactory sessionFactory = getSessionFactory();
		final Session session = sessionFactory == null ? null : sessionFactory.openSession();
		try {
			log.debug("开始初始化权限信息……");
			final Package[] packages = Package.getPackages();
			if (log.isDebugEnabled()) {
				log.debug("获取到当前加载的程序包信息为：" + Arrays.asList(packages));
			}
			if (!ArrayUtils.isEmpty(packages)) {
				final Set<Class<?>> classes = new HashSet<Class<?>>();
				for (Package pack : packages) {
					final String name = pack == null ? null : pack.getName();
					if (StringUtils.startsWith(name, "snow.biz")) {
						if (log.isDebugEnabled()) {
							log.debug("获取包[" + pack + "]所有类信息！");
						}
						classes.addAll(ClassHelper.getClassesFrom(pack));
					}
				}
				if (log.isDebugEnabled()) {
					log.debug("所有系统业务类信息为：" + classes);
				}
				final Set<Privilege> privileges = new HashSet<Privilege>(classes.size());
				final Object entity = session == null ? null : session.get(User.class, getSuperAdminUserId());
				final User superAdminUser = entity instanceof User ? (User) entity : null;
				for (final Class<?> clazz : classes) {
					final Method[] methods = clazz == null ? null : clazz.getDeclaredMethods();
					if (!ArrayUtils.isEmpty(methods)) {
						for (Method method : methods) {
							Operation operation = SecurityHelper.getOperationFrom(method);
							if (operation != null) {
								final String uri = SecurityHelper.getResourceUriFrom(clazz, method); // 资源信息
								final Operator type = operation.type(); // 权限信息
								final String name = operation.name(); // 权限名称
								final String comment = operation.name(); // 权限描述
								final Boolean needCheck = Boolean.valueOf(operation.needCheck()); // 是否验证
								final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Privilege.class);
								detachedCriteria.add(Restrictions.eq("uri", uri));
								detachedCriteria.add(Restrictions.eq("type", type));
								final Criteria criteria = detachedCriteria.getExecutableCriteria(session);
								final Object result = criteria.setProjection(Projections.rowCount()).uniqueResult();
								if (result instanceof Number) {
									final Number number = (Number) result;
									if (number.longValue() == 0) {
										privileges.add(new Privilege(superAdminUser, Status.SUCCESS, uri, type, name, comment, needCheck));
									}
								}
							}
						}
					}
				}
				if (session != null) {
					Transaction transaction = session.beginTransaction();
					try {
						for (Privilege privilege : privileges) {
							session.save(privilege);
						}
						transaction.commit();
					} catch (Exception e) {
						transaction.rollback();
						log.error(e.getMessage(), e);
					}
				}
			}
		} finally {
			if (session != null) {
				session.close();
			}
			log.debug("结束初始化权限信息！");
		}
	}

	public Permission searchPermissionFrom(Object target, Method method) {
		String uri = SecurityHelper.getResourceUriFrom(target, method);
		Operator operator = SecurityHelper.getOperatorFrom(method);
		Conditions conditions = new AndedConditions();
		conditions.addCondition(new Condition("uri", BinaryOperator.EQ, StringUtils.trimToEmpty(uri)));
		conditions.addCondition(new Condition("type", BinaryOperator.EQ, operator));
		conditions.addCondition(new Condition("status", BinaryOperator.EQ, Status.SUCCESS));
		try {
			return super.findForUnique(conditions, Arrays.asList(new Order[] { Order.desc("id") }), Privilege.class);
		} catch (BusinessException e) {
			return null;
		}
	}

	public void setSuperAdminUserId(Integer superAdminUserId) {
		this.superAdminUserId = superAdminUserId;
	}

}
